/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.process.workitem.email; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.List; import java.util.Random; import javax.mail.AuthenticationFailedException; import javax.mail.BodyPart; import javax.mail.Message.RecipientType; import javax.mail.Multipart; import javax.mail.Part; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import org.drools.core.process.instance.impl.DefaultWorkItemManager; import org.drools.core.process.instance.impl.WorkItemImpl; import org.jbpm.test.util.AbstractBaseTest; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.kie.api.runtime.process.WorkItemManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.subethamail.smtp.AuthenticationHandler; import org.subethamail.smtp.AuthenticationHandlerFactory; import org.subethamail.smtp.auth.LoginAuthenticationHandlerFactory; import org.subethamail.smtp.auth.LoginFailedException; import org.subethamail.smtp.auth.MultipleAuthenticationHandlerFactory; import org.subethamail.smtp.auth.PlainAuthenticationHandlerFactory; import org.subethamail.smtp.auth.UsernamePasswordValidator; import org.subethamail.wiser.Wiser; import org.subethamail.wiser.WiserMessage; public class SendHtmlTest extends AbstractBaseTest { private static final Logger logger = LoggerFactory.getLogger(SendHtmlTest.class); private Wiser wiser; private String emailHost; private String emailPort; private static String authUsername = "cpark"; private static String authPassword = "yourbehindwhat?"; private Random random = new Random(); private int uniqueTestNum = -1; @Before public void setUp() throws Exception { uniqueTestNum = random.nextInt(Integer.MAX_VALUE); emailHost = "localhost"; int emailPortInt; do { emailPortInt = random.nextInt((2*Short.MAX_VALUE-1)); } while( emailPortInt < 4096 ); emailPort = Integer.toString(emailPortInt); wiser = new Wiser(Integer.parseInt(emailPort)); wiser.start(); } @After public void tearDown() throws Exception { if( wiser != null ) { wiser.getMessages().clear(); wiser.stop(); wiser = null; } } @SuppressWarnings("unused") private class ExtendedConnection extends Connection { private String extraField; } @Test public void testConnectionEquals() { Connection connA = new Connection(); Connection connB = new Connection(); // null test assertTrue( !connA.equals(null)); // different class test assertTrue( !connA.equals("og")); // extended class test ExtendedConnection connExt = new ExtendedConnection(); assertTrue( !connA.equals(connExt) ); // null fields test assertTrue( connA.equals(connB)); // all null vs filled field test connA.setHost("Human"); connA.setPort("Skin"); connA.setUserName("Viral"); connA.setPassword("Protein Gate"); assertTrue( ! connA.equals(connB)); // filled field test connB.setHost(connA.getHost()); connB.setPort(new String(connA.getPort())); connB.setUserName(connA.getUserName()); connB.setPassword(connA.getPassword()); assertTrue( connA.equals(connB)); // some null vs filled field test connA.setPassword(null); connB.setPassword(null); assertTrue( connA.equals(connB)); // boolean connA.setStartTls(true); assertTrue( !connA.equals(connB)); connB.setStartTls(true); assertTrue( connA.equals(connB)); connB.setStartTls(false); assertTrue( !connA.equals(connB)); } @Test public void verifyWiserServerWorks() throws Exception { // Input String testMethodName = Thread.currentThread().getStackTrace()[1].getMethodName(); String toAddress = "boyd@crowdergang.org"; String fromAddress = "rgivens@kty.us.gov"; // Setup email WorkItemImpl workItem = createEmailWorkItem(toAddress, fromAddress, testMethodName); Connection connection = new Connection(emailHost, emailPort); sendAndCheckThatMessagesAreSent(workItem, connection); } @Test public void sendHtmlWithAuthentication() throws Exception { // Add authentication to Wiser SMTP server wiser.getServer().setAuthenticationHandlerFactory(new TestAuthHandlerFactory()); // Input String testMethodName = Thread.currentThread().getStackTrace()[1].getMethodName(); String toAddress = "rgivens@kty.us.gov"; String fromAddress = "whawkins@kty.us.gov"; // Setup email WorkItemImpl workItem = createEmailWorkItem(toAddress, fromAddress, testMethodName); Connection connection = new Connection(emailHost, emailPort, authUsername, authPassword); sendAndCheckThatMessagesAreSent(workItem, connection); } @Test public void sendHtmlWithAuthenticationAndAttachments() throws Exception { // Add authentication to Wiser SMTP server wiser.getServer().setAuthenticationHandlerFactory(new TestAuthHandlerFactory()); // Input String testMethodName = Thread.currentThread().getStackTrace()[1].getMethodName(); String toAddress = "rgivens@kty.us.gov"; String fromAddress = "whawkins@kty.us.gov"; // Setup email WorkItemImpl workItem = createEmailWorkItemWithAttachment(toAddress, fromAddress, testMethodName); Connection connection = new Connection(emailHost, emailPort, authUsername, authPassword); // send email Email email = EmailWorkItemHandler.createEmail(workItem, connection); SendHtml.sendHtml(email, connection); List<WiserMessage> messages = wiser.getMessages(); assertEquals(1, messages.size()); MimeMessage message = messages.get(0).getMimeMessage(); assertEquals(workItem.getParameter("Subject"), message.getSubject()); assertTrue(Arrays.equals(InternetAddress.parse((String) workItem.getParameter("To")), message.getRecipients(RecipientType.TO))); assertTrue(message.getContent() instanceof Multipart); Multipart multipart = (Multipart) message.getContent(); assertEquals(2, multipart.getCount()); for (int i = 0; i < multipart.getCount(); i++) { BodyPart bodyPart = multipart.getBodyPart(i); if (!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) { continue; // dealing with attachments only } assertEquals("email.gif", bodyPart.getFileName()); } } @Test public void sendHtmlWithBadAuthentication() throws Exception { // Add authentication to Wiser SMTP server wiser.getServer().setAuthenticationHandlerFactory(new TestAuthHandlerFactory()); // Input String testMethodName = Thread.currentThread().getStackTrace()[1].getMethodName(); String toAddress = "mags@bennetstore.com"; String fromAddress = "rgivens@kty.us.gov"; checkBadAuthentication(toAddress, fromAddress, testMethodName, authUsername, "bad password"); checkBadAuthentication(toAddress, fromAddress, testMethodName, "badUserName", authPassword); } @Test public void useEmailWorkItemHandlerWithAuthentication() throws Exception { // Add authentication to Wiser SMTP server wiser.getServer().setAuthenticationHandlerFactory(new TestAuthHandlerFactory()); // Input String testMethodName = Thread.currentThread().getStackTrace()[1].getMethodName(); String toAddress = "rgivens@yahoo.com"; String fromAddress = "rgivens@kty.us.gov"; EmailWorkItemHandler handler = new EmailWorkItemHandler(); handler.setConnection( emailHost, emailPort, authUsername, authPassword ); WorkItemImpl workItem = new WorkItemImpl(); workItem.setParameter( "To", toAddress ); workItem.setParameter( "From", fromAddress ); workItem.setParameter( "Reply-To", fromAddress ); workItem.setParameter( "Subject", "Test mail for " + testMethodName ); workItem.setParameter( "Body", "Don't forget to check on Boyd later today." ); WorkItemManager manager = new DefaultWorkItemManager(null); handler.executeWorkItem( workItem, manager ); List<WiserMessage> messages = wiser.getMessages(); assertEquals(1, messages.size()); for (WiserMessage wiserMessage : messages ) { MimeMessage message = wiserMessage.getMimeMessage(); assertEquals(workItem.getParameter("Subject"), message.getSubject()); assertTrue(Arrays.equals(InternetAddress.parse(toAddress), message.getRecipients(RecipientType.TO))); } } /** * Helper methods */ private void sendAndCheckThatMessagesAreSent(WorkItemImpl workItem, Connection connection) throws Exception { // send email Email email = EmailWorkItemHandler.createEmail(workItem, connection); SendHtml.sendHtml(email, connection); List<WiserMessage> messages = wiser.getMessages(); assertEquals(1, messages.size()); for (WiserMessage wiserMessage : messages ) { MimeMessage message = wiserMessage.getMimeMessage(); assertEquals(workItem.getParameter("Subject"), message.getSubject()); assertTrue(Arrays.equals(InternetAddress.parse((String) workItem.getParameter("To")), message.getRecipients(RecipientType.TO))); } } private void checkBadAuthentication(String toAddress, String fromAddress, String testMethodName, String username, String password) { // Setup email WorkItemImpl workItem = createEmailWorkItem(toAddress, fromAddress, testMethodName); Connection connection = new Connection(emailHost, emailPort, username, password); // send email Email email = EmailWorkItemHandler.createEmail(workItem, connection); try { SendHtml.sendHtml(email, connection); } catch (Throwable t) { assertTrue( "Unexpected exception of type " + t.getClass().getSimpleName() + ", not " + t.getClass().getSimpleName(), (t instanceof RuntimeException)); assertNotNull("Expected RuntimeException to have a cause.", t.getCause()); Throwable cause = t.getCause(); assertNotNull("Expected cause to have a cause.", cause.getCause()); cause = cause.getCause(); assertTrue( "Unexpected exception of type " + cause.getClass().getSimpleName() + ", not " + cause.getClass().getSimpleName(), (cause instanceof AuthenticationFailedException)); } } private WorkItemImpl createEmailWorkItem(String toAddress, String fromAddress, String testMethodName) { WorkItemImpl workItem = new WorkItemImpl(); workItem.setParameter( "To", toAddress ); workItem.setParameter( "From", fromAddress ); workItem.setParameter( "Reply-To", fromAddress ); String subject = this.getClass().getSimpleName() + " test message [" + uniqueTestNum + "]"; String body = "\nThis is the test message generated by the " + testMethodName + " test (" + uniqueTestNum + ").\n"; workItem.setParameter( "Subject", subject ); workItem.setParameter( "Body", body ); return workItem; } private WorkItemImpl createEmailWorkItemWithAttachment(String toAddress, String fromAddress, String testMethodName) { WorkItemImpl workItem = new WorkItemImpl(); workItem.setParameter( "To", toAddress ); workItem.setParameter( "From", fromAddress ); workItem.setParameter( "Reply-To", fromAddress ); String subject = this.getClass().getSimpleName() + " test message [" + uniqueTestNum + "]"; String body = "\nThis is the test message generated by the " + testMethodName + " test (" + uniqueTestNum + ").\n"; workItem.setParameter( "Subject", subject ); workItem.setParameter( "Body", body ); workItem.setParameter("Attachments", "classpath:/icons/email.gif"); return workItem; } private static class TestAuthHandlerFactory implements AuthenticationHandlerFactory { MultipleAuthenticationHandlerFactory authHandleFactory = new MultipleAuthenticationHandlerFactory(); public TestAuthHandlerFactory() { UsernamePasswordValidator validator = new UsernamePasswordValidator() { public void login(String username, String password) throws LoginFailedException { if (!authUsername.equals(username) || !authPassword.equals(password)) { logger.debug("Tried to login with user/password [{}/{}]", username, password); throw new LoginFailedException("Incorrect password for user " + authUsername); } } }; authHandleFactory.addFactory(new LoginAuthenticationHandlerFactory(validator)); authHandleFactory.addFactory(new PlainAuthenticationHandlerFactory(validator)); } public AuthenticationHandler create() { return authHandleFactory.create(); } public List<String> getAuthenticationMechanisms() { return authHandleFactory.getAuthenticationMechanisms(); } } }